#include "wifi_ap.h"
#include <string.h>
#include <stdlib.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_event.h"

#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_mac.h"

#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"


#define TAG     "wifi_ap"
#define EXAMPLE_ESP_WIFI_SSID      "decombutton"
#define EXAMPLE_ESP_WIFI_PASS      "123456789"
#define EXAMPLE_ESP_WIFI_CHANNEL   1
#define EXAMPLE_MAX_STA_CONN       4

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
        ESP_LOGI(pcTaskGetName(nullptr), "station " MACSTR " join, AID=%d", MAC2STR(event->mac), event->aid);
    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
        ESP_LOGI(pcTaskGetName(nullptr), "station " MACSTR " leave, AID=%u", MAC2STR(event->mac), event->aid);
    } else {
        ESP_LOGI(pcTaskGetName(nullptr), "Event ID [%ld]", event_id);
    }
}
 
esp_err_t wifi_init_ap(void)
{
    ESP_LOGI(TAG, "WIFI Start Init");

    ESP_ERROR_CHECK(esp_netif_init());                  /*初始化底层TCP/IP堆栈*/
    ESP_ERROR_CHECK(esp_event_loop_create_default());   /*创建默认事件循环*/
    esp_netif_create_default_wifi_ap();                 /*创建默认WIFI AP,如果出现任何初始化错误,此API将中止*/

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));               /*初始化WiFi为WiFi驱动程序分配资源，如WiFi控制结构、RX/TX缓冲区、WiFi NVS结构等。此WiFi还启动WiFi任务。*/

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                            ESP_EVENT_ANY_ID,
                                                            &wifi_event_handler,
                                                            NULL,
                                                            NULL));

    wifi_config_t wifi_config;
    memset(&wifi_config, 0, sizeof(wifi_config_t));
    // wifi_config.ap.ssid = EXAMPLE_ESP_WIFI_SSID,
    wifi_config.ap.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID);
    memcpy(wifi_config.ap.ssid, EXAMPLE_ESP_WIFI_SSID, wifi_config.ap.ssid_len);
    wifi_config.ap.channel = EXAMPLE_ESP_WIFI_CHANNEL;
    memcpy(wifi_config.ap.password, EXAMPLE_ESP_WIFI_PASS, strlen(EXAMPLE_ESP_WIFI_PASS));
    wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
    wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK;
    wifi_config.ap.pmf_cfg.required = true;

    if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(pcTaskGetName(nullptr), "wifi_init_softap finished. SSID:%s password:%s channel:%d",
            EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
    return ESP_OK;
}


esp_err_t nvs_write_wifi_data(char *confirm_string, char *wifi_name,char *wifi_passwd)
{
    nvs_handle handle;
    // 写入一个整形数据，一个字符串，WIFI信息以及版本信息
    static const char *NVS_CUSTOMER = "storage";
    static const char *DATA2 = "String";
    static const char *DATA3 = "blob_wifi";
    // static const char *DATA4 = "blob_version";

	// 要写入的WIFI信息
    wifi_config_t wifi_config_to_store;

    strcpy((char *)&wifi_config_to_store.sta.ssid,wifi_name);
    strcpy((char *)&wifi_config_to_store.sta.password,wifi_passwd);
    // // 要写入的版本号
    // uint8_t version_for_store[4] = {0x01, 0x01, 0x01, 0x00};
    
    ESP_LOGI(TAG, "set size:%d\r\n", (int)(sizeof(wifi_config_t)));
    ESP_ERROR_CHECK( nvs_open( NVS_CUSTOMER, NVS_READWRITE, &handle) );
    ESP_ERROR_CHECK( nvs_set_str( handle, DATA2, confirm_string) );
    ESP_ERROR_CHECK( nvs_set_blob( handle, DATA3, &wifi_config_to_store, sizeof(wifi_config_to_store)) );
    // ESP_ERROR_CHECK( nvs_set_blob( handle, DATA4, version_for_store, 4) );

    ESP_ERROR_CHECK( nvs_commit(handle) );
    nvs_close(handle);
    return ESP_OK;
}

esp_err_t nvs_read_wifi_data(char *confirm_string, char *wifi_name,char *wifi_passwd)
{
    // strcpy(wifi_name,"CMCC-ET97");
    // strcpy(wifi_passwd,"dhzz9625");
    // return ESP_OK;
    nvs_handle handle;
    static const char *NVS_CUSTOMER = "storage";
    static const char *DATA2 = "String";
    static const char *DATA3 = "blob_wifi";
    // static const char *DATA4 = "blob_version";
    
    size_t str_length = 50;
    char str_data[50] = {0};
    wifi_config_t wifi_config_stored;
    // uint8_t version[4] = {0};
    // uint32_t version_len = 4;
    
    memset(&wifi_config_stored, 0x0, sizeof(wifi_config_stored));
    size_t wifi_len = sizeof(wifi_config_stored);

    ESP_ERROR_CHECK( nvs_open(NVS_CUSTOMER, NVS_READWRITE, &handle) );

    esp_err_t err = nvs_get_str(handle, DATA2, str_data, &str_length);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "read wifi info failed");
        return ESP_FAIL;
    }
    err = nvs_get_blob(handle, DATA3, &wifi_config_stored, &wifi_len);
    // ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA4, version, &version_len) );

    printf("[data1]: %s len:%u\r\n", str_data, str_length);
    printf("[data3]: ssid:%s passwd:%s\r\n", wifi_config_stored.sta.ssid, wifi_config_stored.sta.password);

    strcpy(wifi_name,(char *)&wifi_config_stored.sta.ssid);
    strcpy(wifi_passwd,(char *)&wifi_config_stored.sta.password);

    nvs_close(handle);

    if(strcmp(confirm_string, str_data) == 0) {
        return ESP_OK;
    }
    return ESP_ERR_WIFI_PASSWORD;
}